#ifndef  __DS18B20_H
#define  __DS18B20_H

#if defined (_C51)
#include <REG52.h>
#define DS18B20_DELAY480US  54  //@11.0592MHz
#define DS18B20_DELAY420US  47  //@11.0592MHz
#define DS18B20_DELAY60US   5   //@11.0592MHz

#elif defined (_STC12)
#include <STC12X.h>
#include "STC12_delay.h"
#define DS18B20_DELAY480US  378  //@11.0592MHz
#define DS18B20_DELAY420US  330  //@11.0592MHz
#define DS18B20_DELAY60US   46   //@11.0592MHz

#elif defined (_STC15)
#include <STC15X.h>
#include "STC15_delay.h"
#if (SYS_CLK == 24000000)
#define DS18B20_DELAY480US  885  //@24MHz
#define DS18B20_DELAY420US  775  //@24MHz
#define DS18B20_DELAY60US   110   //@24MHz
#elif (SYS_CLK == 12000000)
#define DS18B20_DELAY480US  444  //@12MHz
#define DS18B20_DELAY420US  387  //@12MHz
#define DS18B20_DELAY60US   54   //@12MHz
#elif (SYS_CLK == 5529600)
#define DS18B20_DELAY480US  204  //@5.5296MHz
#define DS18B20_DELAY420US  177  //@5.5296MHz
#define DS18B20_DELAY60US   24   //@5.5296MHz
#else //11059200
#define DS18B20_DELAY480US  408  //@11.0592MHz
#define DS18B20_DELAY420US  357  //@11.0592MHz
#define DS18B20_DELAY60US   50   //@11.0592MHz
#endif

#elif defined (_STC8)
#include <STC8HX.h>
#include "delay.h"
#define DS18B20_DELAY480US  1150  //@24MHz
#define DS18B20_DELAY420US  1008  //@24MHz
#define DS18B20_DELAY60US   143   //@24MHz

#else   //STC16
#include <STC16F.h>
#include "delay.h"
#define DS18B20_DELAY480US  1150  //@24MHz
#define DS18B20_DELAY420US  1008  //@24MHz
#define DS18B20_DELAY60US   143   //@24MHz
#endif


#ifndef DS18B20_DQ
#define DS18B20_DQ            P4_7
#endif
#ifndef DS18B20_DQ_MODE
#define DS18B20_DQ_MODE       {P4M1&=~0x80;P4M0&=~0x80;}//双向IO口
#endif 

void ds18b20_delay(uint16 count);

void ds18b20_init();
float ds18b20_read_temperature();

//========================================================================
// 描述: DS18B20初始化.
// 参数: none.
// 返回: none.
//========================================================================
void ds18b20_init()
{
    #ifndef    _C51
        DS18B20_DQ_MODE;//双向IO口
    #endif 
    DS18B20_DQ = 1;  
}

//========================================================================
// 描述: DS18B20总线复位.
// 参数: none.
// 返回: 0,复位成功;1,复位失败.
//========================================================================
uint8 ds18b20_reset()
{
    uint8 ds18b20_retry;
    ds18b20_retry = 0;
    while (1)
    {
        ds18b20_retry++;
        if(ds18b20_retry >= 10)return 1;
        DS18B20_DQ = 1; 
        DS18B20_DQ = 0;             //送出低电平复位信号
        ds18b20_delay(DS18B20_DELAY480US);  //延时至少480us
        DS18B20_DQ = 1;                     //释放数据线
        ds18b20_delay(DS18B20_DELAY60US);   //等待60us
        if(DS18B20_DQ == 0)                  //检测存在脉冲
        {
            ds18b20_delay(DS18B20_DELAY420US);
            return 0;
        }
        ds18b20_delay(DS18B20_DELAY420US);        //等待设备释放数据线
    }
}

//========================================================================
// 描述: 从DS18B20读1字节数据.
// 参数: none.
// 返回: 1字节数据.
//========================================================================
uint8 ds18b20_read_byte()
{
    uint8 i;
    uint8 dat = 0;

    for (i=0; i<8; i++)             //8位计数器
    {
        dat >>= 1;
        DS18B20_DQ = 0;                     //开始时间片

        #if defined (_C51)
        _nop_();                //延时等待
        #else
        delay1us(); 
        #endif

        DS18B20_DQ = 1;                     //准备接收

        #if defined (_C51)
        _nop_();                //延时等待
        #else
        delay1us(); 
        #endif

        if (DS18B20_DQ) dat |= 0x80;        //读取数据
        ds18b20_delay(DS18B20_DELAY60US);   //等待时间片结束
    }

    return dat;
}

//========================================================================
// 描述: 向DS18B20写1字节数据.
// 参数: 1字节数据.
// 返回: none.
//========================================================================
void ds18b20_write_byte(uint8 dat)
{
    char i;

    for (i=0; i<8; i++)             //8位计数器
    {
        DS18B20_DQ = 0;                     //开始时间片

        #if defined (_C51)
        _nop_();
        #else
        delay1us();               //延时等待
        #endif

        dat >>= 1;                  //送出数据
        DS18B20_DQ = CY;
        ds18b20_delay(DS18B20_DELAY60US);    //等待时间片结束
        DS18B20_DQ = 1;                     //恢复数据线

         #if defined (_C51)
        _nop_();                
        #else
        delay1us();                //恢复延时
        #endif
    }
}

//========================================================================
// 描述: 读取温度.
// 参数: none.
// 返回: 温度值(返回255代表读取失败).
//========================================================================
float ds18b20_read_temperature()
{
    uint16 TempH, TempL, Temperature;
	uint16 ds18b20_retry;
    ds18b20_retry = 0;

    if(ds18b20_reset())      //设备复位
    {
        return 255; //返回错误代码
    }            
    ds18b20_write_byte(0xCC);        //跳过ROM命令
    ds18b20_write_byte(0x44);        //开始转换命令
    
    while (!DS18B20_DQ && ds18b20_retry++ < 400)                    //等待转换完成
    {
		delay(1);
    }
    if(ds18b20_retry >= 400)
    {
        return 255;  //返回错误代码
    }
    if(ds18b20_reset())      //设备复位
    {
        return 255; //返回错误代码
    }    
    ds18b20_write_byte(0xCC);        //跳过ROM命令
    ds18b20_write_byte(0xBE);        //读暂存存储器命令
    TempL = ds18b20_read_byte();     //读温度低字节
    TempH = ds18b20_read_byte();     //读温度高字节
	
    if(TempH & 0xf8)    //如果为负数
    {
       // MinusFlag = 1;  //设置负数标志
        Temperature = (TempH<<8) | TempL;
        Temperature = ~Temperature+1;
        return (float)Temperature*-0.625/10.0;
    }
    else
    {
        //MinusFlag = 0;  //清除负数标志
        Temperature = (TempH<<8) | TempL; //0.0625 * 10，保留1位小数点
        return (float)Temperature*0.625/10.0;
    }
}

//========================================================================
// 描述: DS18B20特定延时函数.
// 参数: none.
// 返回: none.
//========================================================================
void ds18b20_delay(uint16 count)
{
    do{
        _nop_();
    }while(--count);
}

#endif  //ds18b20.h